#pragma once

#include "task_types.h"
#include "cancellation_token.h"

#include <QObject>
#include <QMutex>
#include <QThread>
#include <QTimer>
#include <QUuid>
#include <QVariant>

#include <functional>
#include <memory>

namespace base::tasking {

/**
 * @brief 任务句柄，作为主线程与后台任务之间的通信桥梁
 */
class TaskHandle : public QObject {
    Q_OBJECT
public:
    enum class Status {
        Pending,
        Running,
        Finished,
        Canceled,
        Error
    };

    using Ptr = std::shared_ptr<TaskHandle>;

    static Ptr create(const QString& taskId = QString(),
                      const QString& batchId = QString(),
                      QObject* parent = nullptr);

    ~TaskHandle() override = default;

    QString id() const;
    QString batchId() const;

    Status status() const;
    bool isCanceled() const;
    void requestCancel();
    CancellationTokenPtr cancellationToken() const;

    kernel::ErrorCode errorCode() const;
    QString errorMessage() const;

    void setTimeout(int timeoutMs);
    int timeout() const;

    template<typename T>
    std::optional<T> resultAs() const {
        QMutexLocker locker(&m_mutex);
        if (!m_payload.isValid() || !m_payload.canConvert<T>()) {
            return std::nullopt;
        }
        return m_payload.value<T>();
    }

    void notifyRunning();
    void notifySuccess(TaskResult result);
    void notifyFailure(TaskResult result);
    void notifyCanceled();

signals:
    void taskFinished(const TaskResult& result);

private:
    struct Deleter {
        void operator()(TaskHandle* handle) const;
    };

    explicit TaskHandle(QString taskId, QString batchId, QObject* parent);

    void enqueueStatusChange(std::function<void()> fn);

    mutable QMutex m_mutex;
    QString m_taskId;
    QString m_batchId;
    Status m_status = Status::Pending;
    kernel::ErrorCode m_errorCode = kernel::ErrorCode::Success;
    QString m_errorMessage;
    QVariant m_payload;
    CancellationTokenPtr m_cancellationToken;

    QTimer* m_timeoutTimer = nullptr;
    int m_timeoutMs = 30000; // Default 30 seconds
    qint64 m_startTime = 0;

    void startTimeoutTimer();
    void stopTimeoutTimer();
    void onTimeout();
};

} // namespace base::tasking
